package com.zxmzy.scaffold.core.utils

import android.content.Context
import android.os.Parcelable
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.tencent.mmkv.MMKV
import com.zxmzy.scaffold.core.ext.toJson
import java.lang.reflect.Type

/**
 * @author zhangxiaoming
 * @date 2023/8/31
 * @description
 */
object MMKVUtil {
    private val mGson = Gson()
    private lateinit var mmkv: MMKV

    fun init(context: Context){
        MMKV.initialize(context)
        mmkv = MMKV.defaultMMKV()
    }

    @JvmStatic
    fun encode(key: String, value: Any): Boolean {
        return when (value) {
            is Boolean -> mmkv.encode(key, value)
            is Int -> mmkv.encode(key, value)
            is Float -> mmkv.encode(key, value)
            is Double -> mmkv.encode(key, value)
            is Long -> mmkv.encode(key, value)
            is String -> mmkv.encode(key, value)
            is ByteArray -> mmkv.encode(key, value)
            is Parcelable -> mmkv.encode(key, value)
            else -> {
                val strJson = value.toJson()
                mmkv.encode(key, strJson)
            }
        }
    }

    @JvmStatic
    fun encode(key: String, value: Set<String>): Boolean {
        return mmkv.encode(key, value)
    }

    @JvmStatic
    fun <T> decodeObj(key: String, clazz: Class<T>): T? {
        val jsonStr: String? = mmkv.decodeString(key, null)
        jsonStr?.let {
            return mGson.fromJson(jsonStr, clazz)
        }
        return null
    }

    @JvmStatic
    fun <T> encodeList(key: String, value: List<T>): Boolean {
        return mmkv.encode(key, value.toJson())
    }

    @JvmStatic
    fun <T> decodeList(key: String): List<T> {
        val jsonStr = mmkv.decodeString(key, null)
        jsonStr?.let {
            val type: Type = object : TypeToken<List<T>>() {}.type
            return mGson.fromJson(jsonStr, type)
        }
        return emptyList()
    }

    @JvmStatic
    fun decodeStringSet(key: String): Set<String>? = mmkv.decodeStringSet(key)

    @JvmStatic
    fun decodeStringSet(key: String, defaultValue: Set<String>): Set<String>? =
        mmkv.decodeStringSet(key, defaultValue)

    @JvmStatic
    fun decodeBool(key: String): Boolean = mmkv.decodeBool(key)

    @JvmStatic
    fun decodeBool(key: String, defaultValue: Boolean): Boolean = mmkv.decodeBool(key, defaultValue)

    @JvmStatic
    fun decodeInt(key: String): Int = mmkv.decodeInt(key)

    @JvmStatic
    fun decodeInt(key: String, defaultValue: Int): Int = mmkv.decodeInt(key, defaultValue)

    @JvmStatic
    fun decodeFloat(key: String): Float = mmkv.decodeFloat(key)

    @JvmStatic
    fun decodeFloat(key: String, defaultValue: Float): Float = mmkv.decodeFloat(key, defaultValue)

    @JvmStatic
    fun decodeDouble(key: String): Double = mmkv.decodeDouble(key)

    @JvmStatic
    fun decodeDouble(key: String, defaultValue: Double): Double =
        mmkv.decodeDouble(key, defaultValue)

    @JvmStatic
    fun decodeLong(key: String): Long = mmkv.decodeLong(key)

    @JvmStatic
    fun decodeLong(key: String, defaultValue: Long): Long = mmkv.decodeLong(key, defaultValue)

    @JvmStatic
    fun decodeString(key: String): String? = mmkv.decodeString(key)

    @JvmStatic
    fun decodeString(key: String, defaultValue: String): String? =
        mmkv.decodeString(key, defaultValue)

    @JvmStatic
    fun decodeByteArray(key: String): ByteArray? = mmkv.decodeBytes(key)

    @JvmStatic
    fun decodeByteArray(key: String, defaultValue: ByteArray): ByteArray? =
        mmkv.decodeBytes(key, defaultValue)

    @JvmStatic
    fun <T : Parcelable> decodeParcelable(key: String, clazz: Class<T>): T? =
        mmkv.decodeParcelable(key, clazz)

    @JvmStatic
    fun <T : Parcelable> decodeParcelable(key: String, clazz: Class<T>, defaultValue: T): T? =
        mmkv.decodeParcelable(key, clazz, defaultValue)
}